<?php
declare(strict_types=1);

namespace app\controller;

use app\BaseController;
use app\model\MaterialCategoryModel;
use app\model\ProductModel;
use think\facade\Db;
use think\facade\Request;
use think\facade\Validate;

/**
 * 仓库模块控制器
 */
class Warehouse extends BaseController
{
    /**
     * 获取入库单列表
     */
    public function getInboundList()
    {
        $page = (int)Request::param('page', 1);
        $limit = (int)Request::param('limit', 10);
        $search = Request::param('search', '');
        $inbound_type = Request::param('inbound_type', '');
        $status = Request::param('status', '');
        $start_date = Request::param('start_date', '');
        $end_date = Request::param('end_date', '');
        $type = Request::param('type', '');

        $where = [];
        if (!empty($search)) {
            $where[] = ['inbound_no|related_order_no', 'like', "%{$search}%"];
        }
        if (!empty($inbound_type)) {
            $where[] = ['inbound_type', '=', $inbound_type];
        }
        if ($status !== '') {
            $where[] = ['status', '=', (int)$status];
        }
        if (!empty($type)) {
            $where[] = ['wi.type', '=', $type];
        }
        if (!empty($start_date) && !empty($end_date)) {
            $where[] = ['inbound_date', 'between', [$start_date, $end_date]];
        } else if (!empty($start_date)) {
            $where[] = ['inbound_date', '>=', $start_date];
        } else if (!empty($end_date)) {
            $where[] = ['inbound_date', '<=', $end_date];
        }

        $user = getUserInfo();
        $dataRole = dataPermissionCheck($user);
        if (in_array($dataRole, ['user', 'company'])) {
            $where[] = ['wi.company_id', '=', $user['company_id']];
        }

        // 获取入库单列表
        $list = Db::name('warehouse_inbound')
            ->alias('wi')
            ->leftJoin('user u', 'wi.operator_id = u.id')
            ->leftJoin('user ur', 'wi.reviewer_id = ur.id')
            ->leftJoin('supplier s', 'wi.supplier_id = s.id')
            ->leftJoin('warehouse w', 'wi.warehouse_id = w.id')
            ->field('wi.*, u.realname as operator_name, ur.realname as reviewer_name, s.supplier_name, w.warehouse_name')
            ->where($where)
            ->page($page, $limit)
            ->order('wi.id', 'desc')
            ->select()
            ->toArray();

        $count = Db::name('warehouse_inbound')->alias('wi')->where($where)->count();

        // 修改返回格式，将list和total包装在data对象中
        return json(['code' => 200, 'msg' => '获取成功', 'data' => ['list' => $list, 'total' => $count]]);
    }

    /**
     * 添加入库单
     */
    public function addInbound()
    {
        $data = Request::post();

        // 验证主表数据
        $validate = Validate::rule([
            'inbound_type' => 'require',
            'operator_id' => 'require|number',
            'warehouse_id' => 'require|number',
            'inbound_date' => 'require|date',
            'status' => 'require|number',
            'type' => 'require|in:100,200',
        ]);

        if (!$validate->check($data)) {
            $errorMsg = $validate->getError();
            file_put_contents(__DIR__ . '/log250825/inbound_add.log', date('Y-m-d H:i:s') . ' - 验证失败: ' . $errorMsg . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => $errorMsg]);
        }

        // 开启事务
        Db::startTrans();
        try {
            // 生成入库单号 (更短的格式)
            $data['inbound_no'] = 'RK' . date('ymdHis') . rand(100, 999);
            $user = $this->getUserInfo();
            // 处理主表数据
            $mainData = [
                'company_id' => $user['company_id'],
                'inbound_no' => $data['inbound_no'],
                'inbound_type' => $data['inbound_type'],
                'related_order_no' => $data['related_order_no'] ?? '',
                'warehouse_id' => $data['warehouse_id'],
                'inbound_date' => $data['inbound_date'],
                'operator_id' => $data['operator_id'],
                'remark' => $data['remark'] ?? '',
                'status' => $data['status'] ?? '1',
                'type' => $data['type'],
                'create_time' => date('Y-m-d H:i:s'),
                'update_time' => date('Y-m-d H:i:s')
            ];

            // 只有当supplier_id存在且不为undefined时才添加
            if (isset($data['supplier_id']) && $data['supplier_id'] !== 'undefined' && $data['supplier_id'] !== '') {
                $mainData['supplier_id'] = intval($data['supplier_id']);
            }

            // 如果状态为已审核，添加审核信息
            if ($data['status'] == 2) {
                $mainData['reviewer_id'] = $data['operator_id']; // 默认审核人为操作人
                $mainData['review_time'] = date('Y-m-d H:i:s');
            }

            // 记录主表数据
            file_put_contents(__DIR__ . '/log250825/inbound_add.log', date('Y-m-d H:i:s') . ' - 主表数据: ' . json_encode($mainData, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

            // 插入主表数据
            $inboundId = Db::name('warehouse_inbound')->insertGetId($mainData);
            $data['details'] = json_decode($data['details'], true);
            // 处理明细表数据
            if (!empty($data['details']) && is_array($data['details'])) {
                $totalAmount = 0;
                $detailsData = [];

                // 查询warehouse_inbound_detail表结构
                $tableInfo = Db::query("SHOW COLUMNS FROM fy_warehouse_inbound_detail");
                $fields = array_column($tableInfo, 'Field');
                file_put_contents(__DIR__ . '/log250825/inbound_add.log', date('Y-m-d H:i:s') . ' - 表字段: ' . json_encode($fields, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                foreach ($data['details'] as $detail) {
                    // 记录每条明细数据
                    file_put_contents(__DIR__ . '/log250825/inbound_add.log', date('Y-m-d H:i:s') . ' - 处理明细: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                    // 验证明细数据
                    if (!isset($detail['actual_quantity'])) {
                        file_put_contents(__DIR__ . '/log250825/inbound_add.log', date('Y-m-d H:i:s') . ' - 明细数据验证失败: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                        throw new \Exception('物料ID和实际数量不能为空');
                    }

                    // 确保数值类型正确
                    $material_id = intval($detail['material_id']) ?? 0;
                    $product_id = intval($detail['product_id']) ?? 0;
                    $actual_quantity = floatval($detail['actual_quantity']);
                    $unit_price = floatval($detail['unit_price'] ?? 0);
                    $amount = $unit_price * $actual_quantity;
                    $totalAmount += $amount;


                    // 准备明细数据
                    $detailData = [
                        'inbound_id' => $inboundId,
                        'product_id' => $product_id,
                        'material_id' => $material_id,
                        'actual_quantity' => $actual_quantity,
                        'unit_price' => $unit_price,
                        'amount' => $amount,
                        'batch_no' => $detail['batch_no'] ?? '',
                        'production_date' => $detail['production_date'] ?? null,
                        'create_time' => date('Y-m-d H:i:s'),
                        'update_time' => date('Y-m-d H:i:s')
                    ];

                    // 检查是否有shelf_id字段
                    if (in_array('shelf_id', $fields) && !empty($detail['shelf_id'])) {
                        $detailData['shelf_id'] = intval($detail['shelf_id']);
                    }
                    // 检查是否有quality_status字段
                    if (in_array('quality_status', $fields)) {
                        $detailData['quality_status'] = isset($detail['quality_status']) ? intval($detail['quality_status']) : 1;
                    }

                    $detailsData[] = $detailData;
                }


                // 批量插入明细数据
                if (!empty($detailsData)) {
                    if ($mainData['type'] == 100) {
                        Db::name('warehouse_inbound_detail')->insertAll($detailsData);

                        if ($mainData['status'] == 2) { //代表已经审核  直接入库
                            foreach ($detailsData as $value) {  //更新库存
                                (new MaterialCategoryModel())->stockInOut($value['material_id'], $value['actual_quantity'], '入库单(入库)',
                                    $inboundId);
                            }
                        }
                    } else {
                        Db::name('warehouse_inbound_detail')->insertAll($detailsData);

                        if ($mainData['status'] == 2) { //代表已经审核  直接入库
                            foreach ($detailsData as $value) {  //更新库存
                                (new MaterialCategoryModel())->stockInOutProduct($value['product_id'], $value['actual_quantity'], '入库单(入库)',
                                    $inboundId);
                            }
                        }
                    }
                } else {
                    throw new \Exception('没有明细数据或格式不正确');
                }
                // 更新
                //主表总金额
                Db::name('warehouse_inbound')->where('id', $inboundId)->update([
                    'total_amount' => $totalAmount,
                    'update_time' => date('Y-m-d H:i:s')
                ]);
            } else {
                file_put_contents(__DIR__ . '/log250825/inbound_add.log', date('Y-m-d H:i:s') . ' - 没有明细数据或格式不正确: ' . json_encode($data['details'] ?? null, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
            }

            Db::commit();
            return json(['code' => 200, 'msg' => '添加成功', 'data' => ['id' => $inboundId]]);
        } catch (\Exception $e) {
            Db::rollback();
            file_put_contents(__DIR__ . '/log250825/inbound_add.log', date('Y-m-d H:i:s') . ' - 异常: ' . $e->getMessage() . PHP_EOL . $e->getTraceAsString() . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => '添加失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 更新入库单
     */
    public function updateInbound()
    {
        $data = Request::post();

        // 记录接收到的数据
        file_put_contents(__DIR__ . '/log250825/inbound_update.log', date('Y-m-d H:i:s') . ' - 接收到的数据: ' . json_encode($data, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

        // 检查数据类型
        if (isset($data['details'])) {
            if (!is_array($data['details'])) {
                file_put_contents(__DIR__ . '/log250825/inbound_update.log', date('Y-m-d H:i:s') . ' - details不是数组: ' . gettype($data['details']) . PHP_EOL, FILE_APPEND);
                // 尝试解码JSON字符串
                if (is_string($data['details'])) {
                    $data['details'] = json_decode($data['details'], true);
                    file_put_contents(__DIR__ . '/log250825/inbound_update.log', date('Y-m-d H:i:s') . ' - 解码后的details: ' . json_encode($data['details'], JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                }
            }
        }

        $validate = Validate::rule([
            'id' => 'require|number',
            'inbound_type' => 'require',
            'operator_id' => 'require|number',
            'warehouse_id' => 'require|number',
            'inbound_date' => 'require|date',
            'status' => 'require|number',
            'type' => 'require|in:100,200',
        ]);

        if (!$validate->check($data)) {
            $errorMsg = $validate->getError();
            file_put_contents(__DIR__ . '/log250825/inbound_update.log', date('Y-m-d H:i:s') . ' - 验证失败: ' . $errorMsg . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => $errorMsg]);
        }

        // 检查入库单是否存在
        $inbound = Db::name('warehouse_inbound')->where('id', $data['id'])->find();
        if (!$inbound) {
            return json(['code' => 404, 'msg' => '入库单不存在']);
        }
        if ($inbound['status'] == 2) {
            return json(['code' => 400, 'msg' => '入库单已审核，不允许修改']);
        }

        // 开启事务
        Db::startTrans();
        try {
            // 处理主表数据
            $mainData = [
                'inbound_type' => $data['inbound_type'],
                'related_order_no' => $data['related_order_no'] ?? '',
                'warehouse_id' => $data['warehouse_id'],
                'inbound_date' => $data['inbound_date'],
                'operator_id' => $data['operator_id'],
                'status' => $data['status'],
                'type' => $data['type'],
                'remark' => $data['remark'] ?? '',
                'update_time' => date('Y-m-d H:i:s')
            ];

            // 只有当supplier_id存在且不为undefined时才添加
            if (isset($data['supplier_id']) && $data['supplier_id'] !== 'undefined' && $data['supplier_id'] !== '') {
                $mainData['supplier_id'] = intval($data['supplier_id']);
            }

            // 如果原状态未审核，新状态为已审核，添加审核信息
            if ($inbound['status'] == 1 && $data['status'] == 2) {
                $mainData['reviewer_id'] = $data['operator_id']; // 默认审核人为操作人
                $mainData['review_time'] = date('Y-m-d H:i:s');
            }

            // 记录主表数据
            file_put_contents(__DIR__ . '/log250825/inbound_update.log', date('Y-m-d H:i:s') . ' - 主表数据: ' . json_encode($mainData, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

            // 更新主表数据
            Db::name('warehouse_inbound')->where('id', $data['id'])->update($mainData);

            // 处理明细表数据
            if (!empty($data['details']) && is_array($data['details'])) {
                // 删除原有明细
                Db::name('warehouse_inbound_detail')->where('inbound_id', $data['id'])->delete();

                $totalAmount = 0;
                $detailsData = [];

                // 查询warehouse_inbound_detail表结构
                $tableInfo = Db::query("SHOW COLUMNS FROM fy_warehouse_inbound_detail");
                $fields = array_column($tableInfo, 'Field');
                file_put_contents(__DIR__ . '/log250825/inbound_update.log', date('Y-m-d H:i:s') . ' - 表字段: ' . json_encode($fields, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                foreach ($data['details'] as $detail) {
                    // 验证明细数据
                    if (!isset($detail['actual_quantity'])) {
                        file_put_contents(__DIR__ . '/log250825/inbound_update.log', date('Y-m-d H:i:s') . ' - 明细数据验证失败: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                        throw new \Exception('物料ID和实际数量不能为空');
                    }

                    $amount = ($detail['unit_price'] ?? 0) * ($detail['actual_quantity'] ?? 0);
                    $totalAmount += $amount;

                    // 准备明细数据
                    $detailData = [
                        'inbound_id' => $data['id'],
                        'product_id' => $detail['product_id'] ?? 0,
                        'material_id' => $detail['material_id'] ?? 0,
                        'actual_quantity' => $detail['actual_quantity'],
                        'unit_price' => $detail['unit_price'] ?? 0,
                        'amount' => $amount,
                        'batch_no' => $detail['batch_no'] ?? '',
                        'production_date' => $detail['production_date'] ?? null,
                        'create_time' => date('Y-m-d H:i:s'),
                        'update_time' => date('Y-m-d H:i:s')
                    ];

                    // 检查是否有shelf_id字段
                    if (in_array('shelf_id', $fields) && !empty($detail['shelf_id'])) {
                        $detailData['shelf_id'] = intval($detail['shelf_id']);
                    }

                    // 检查是否有quality_status字段
                    if (in_array('quality_status', $fields)) {
                        $detailData['quality_status'] = isset($detail['quality_status']) ? intval($detail['quality_status']) : 1;
                    }

                    $detailsData[] = $detailData;
                }

                // 批量插入明细数据
                if (!empty($detailsData)) {
                    Db::name('warehouse_inbound_detail')->insertAll($detailsData);
                    if ($mainData['type'] == 100) {
                        if ($mainData['status'] == 2) {
                            foreach ($detailsData as $value) {  //更新库存
                                (new MaterialCategoryModel())->stockInOut($value['material_id'], $value['actual_quantity'], '入库单(入库)',
                                    $inbound['id']);
                            }
                        }
                    } else {
                        if ($mainData['status'] == 2) {
                            foreach ($detailsData as $value) {  //更新库存
                                (new MaterialCategoryModel())->stockInOutProduct($value['product_id'],
                                    $value['actual_quantity'], '入库单(入库)',
                                    $inbound['id']);
                            }
                        }
                    }

                } else {
                    throw new \Exception('入库明细数据不能为空');
                }

                // 更新主表总金额
                Db::name('warehouse_inbound')->where('id', $data['id'])->update([
                    'total_amount' => $totalAmount,
                    'update_time' => date('Y-m-d H:i:s')
                ]);
            }

            Db::commit();
            return json(['code' => 200, 'msg' => '更新成功']);
        } catch (\Exception $e) {
            Db::rollback();
            return json(['code' => 400, 'msg' => '更新失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 删除入库单
     */
    public function deleteInbound()
    {
        $id = Request::param('id');
        $ids = Request::param('ids');

        if (empty($id) && empty($ids)) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }

        Db::startTrans();
        try {
            if (!empty($ids)) {
                // 批量删除
                $idArray = explode(',', $ids);
                foreach ($idArray as $inboundId) {
                    // 删除入库单明细
                    Db::name('warehouse_inbound_detail')->where('inbound_id', $inboundId)->delete();
                    // 删除入库单
                    Db::name('warehouse_inbound')->delete($inboundId);
                }
            } else {
                // 单个删除
                // 删除入库单明细
                Db::name('warehouse_inbound_detail')->where('inbound_id', $id)->delete();
                // 删除入库单
                Db::name('warehouse_inbound')->delete($id);
            }

            Db::commit();
            return json(['code' => 200, 'msg' => '删除成功']);
        } catch (\Exception $e) {
            Db::rollback();
            return json(['code' => 400, 'msg' => '删除失败：' . $e->getMessage()]);
        }
    }

    /**
     * 获取入库单详情
     */
    public function getInboundDetail()
    {
        $id = Request::param('id');

        if (empty($id)) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }

        // 获取主表信息
        $inbound = Db::name('warehouse_inbound')
            ->alias('wi')
            ->leftJoin('user u', 'wi.operator_id = u.id')
            ->leftJoin('user ur', 'wi.reviewer_id = ur.id')
            ->leftJoin('supplier s', 'wi.supplier_id = s.id')
            ->leftJoin('warehouse w', 'wi.warehouse_id = w.id')
            ->field('wi.*, u.realname as operator_name, ur.realname as reviewer_name, s.supplier_name, w.warehouse_name')
            ->where('wi.id', $id)
            ->find();

        if (!$inbound) {
            return json(['code' => 404, 'msg' => '入库单不存在']);
        }

        if ($inbound['type'] == 100) {
            // 获取明细信息
            $details = Db::name('warehouse_inbound_detail')
                ->alias('wid')
                ->leftJoin('material_category mc', 'wid.material_id = mc.id')
                ->leftJoin('shelf s', 'wid.shelf_id = s.id')
                ->field('wid.*, mc.material_name, mc.material_code, s.shelf_code')
                ->where('wid.inbound_id', $id)
                ->select()
                ->toArray();
        } else {
            // 获取明细信息
            $details = Db::name('warehouse_inbound_detail')
                ->alias('wid')
                ->leftJoin('product p', 'wid.product_id = p.id')
                ->leftJoin('shelf s', 'wid.shelf_id = s.id')
                ->field('wid.*, p.product_name, p.product_code, s.shelf_code')
                ->where('wid.inbound_id', $id)
                ->select()
                ->toArray();
        }


        $inbound['details'] = $details;

        return json(['code' => 200, 'msg' => '获取成功', 'data' => $inbound]);
    }

    /**
     * 获取出库单列表
     */
    public function getOutboundList()
    {
        $page = (int)Request::param('page', 1);
        $limit = (int)Request::param('limit', 10);
        $search = Request::param('search', '');
        $status = Request::param('status', '');
        $outbound_type = Request::param('outbound_type', '');
        $start_date = Request::param('start_date', '');
        $end_date = Request::param('end_date', '');
        $type = Request::param('type', '');

        $where = [];
        if (!empty($search)) {
            $where[] = ['outbound_no|related_order_no', 'like', "%{$search}%"];
        }

        if ($status !== '') {
            $where[] = ['status', '=', (int)$status];
        }

        if ($outbound_type !== '') {
            $where[] = ['outbound_type', '=', $outbound_type];
        }
        if ($type !== '') {
            $where[] = ['wo.type', '=', $type];
        }

        if (!empty($start_date) && !empty($end_date)) {
            $where[] = ['outbound_date', 'between', [$start_date, $end_date]];
        } else if (!empty($start_date)) {
            $where[] = ['outbound_date', '>=', $start_date];
        } else if (!empty($end_date)) {
            $where[] = ['outbound_date', '<=', $end_date];
        }


        $user = getUserInfo();
        $dataRole = dataPermissionCheck($user);
        if (in_array($dataRole, ['user', 'company'])) {
            $where[] = ['company_id', '=', $user['company_id']];
        }

        // 获取出库单列表
        $list = Db::name('warehouse_outbound')
            ->alias('wo')
            ->leftJoin('user u', 'wo.operator_id = u.id')
            ->leftJoin('user ur', 'wo.reviewer_id = ur.id')
            ->leftJoin('customer c', 'wo.customer_id = c.id')
            ->leftJoin('warehouse w', 'wo.warehouse_id = w.id')
            ->field('wo.*, u.realname as operator_name, ur.realname as reviewer_name, c.customer_name, w.warehouse_name')
            ->where($where)
            ->page($page, $limit)
            ->order('wo.id', 'desc')
            ->select()
            ->toArray();

        $count = Db::name('warehouse_outbound')->alias('wo')->where($where)->count();

        // 记录日志
        file_put_contents(__DIR__ . '/log250825/outbound_list.log', date('Y-m-d H:i:s') . ' - 获取出库单列表: ' . json_encode([
                'page' => $page,
                'limit' => $limit,
                'search' => $search,
                'outbound_type' => $outbound_type,
                'status' => $status,
                'start_date' => $start_date,
                'end_date' => $end_date,
                'count' => $count
            ], JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

        // 修改返回格式，将list和total包装在data对象中
        return json(['code' => 200, 'msg' => '获取成功', 'data' => ['list' => $list, 'total' => $count]]);
    }

    /**
     * 添加出库单
     */
    public function addOutbound()
    {
        $data = Request::post();

        // 记录接收到的数据
        file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - 接收到的数据: ' . json_encode($data, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

        // 检查数据类型
        if (isset($data['details'])) {
            if (!is_array($data['details'])) {
                file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - details不是数组: ' . gettype($data['details']) . PHP_EOL, FILE_APPEND);
                // 尝试解码JSON字符串
                if (is_string($data['details'])) {
                    $data['details'] = json_decode($data['details'], true);
                    file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - 解码后的details: ' . json_encode($data['details'], JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                }
            }
        }

        $validate = Validate::rule([
            'outbound_type' => 'require',
            'operator_id' => 'require|number',
            'warehouse_id' => 'require|number',
            'outbound_date' => 'require|date',
            'status' => 'require|number',
            'type' => 'require|in:100,200',
        ]);

        if (!$validate->check($data)) {
            $errorMsg = $validate->getError();
            file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - 验证失败: ' . $errorMsg . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => $errorMsg]);
        }

        if (empty($data['details'])) {
            return json(['code' => 400, 'msg' => '请添加出库明细']);
        }
        if ($data['type'] == 100) {
            foreach ($data['details'] as $item) {
                $material = MaterialCategoryModel::where('id', $item['material_id'])->find();
                if ($material->current_quantity < $item['quantity']) {
                    return json(['code' => 400, 'msg' => $material['material_name'] . '库存不足']);
                }
            }
        } else {
            foreach ($data['details'] as $item) {
                $product = ProductModel::where('id', $item['product_id'])->find();
                if ($product->current_quantity < $item['quantity']) {
                    return json(['code' => 400, 'msg' => $product['product_name'] . '库存不足']);
                }
            }
        }


        // 开启事务
        Db::startTrans();
        try {
            // 生成出库单号 (更短的格式)
            $data['outbound_no'] = 'CK' . date('ymdHis') . rand(10, 99);
            $user = $this->getUserInfo();

            // 处理主表数据
            $mainData = [
                'company_id' => $user['company_id'],
                'outbound_no' => $data['outbound_no'],
                'outbound_type' => $data['outbound_type'],
                'related_order_no' => $data['related_order_no'] ?? '',
                'warehouse_id' => $data['warehouse_id'],
                'outbound_date' => $data['outbound_date'],
                'operator_id' => $data['operator_id'],
                'status' => $data['status'],
                'type' => $data['type'],
                'remark' => $data['remark'] ?? '',
                'create_time' => date('Y-m-d H:i:s'),
                'update_time' => date('Y-m-d H:i:s')
            ];

            // 只有当customer_id存在且不为undefined时才添加
            if (isset($data['customer_id']) && $data['customer_id'] !== 'undefined' && $data['customer_id'] !== '') {
                $mainData['customer_id'] = intval($data['customer_id']);
            }

            // 如果状态为已审核，添加审核信息
            if ($data['status'] == 2) {
                $mainData['reviewer_id'] = $data['operator_id']; // 默认审核人为操作人
                $mainData['review_time'] = date('Y-m-d H:i:s');
            }

            // 记录主表数据
            file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - 主表数据: ' . json_encode($mainData, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

            // 插入主表数据
            $outboundId = Db::name('warehouse_outbound')->insertGetId($mainData);

            // 处理明细表数据
            if (!empty($data['details']) && is_array($data['details'])) {
                $totalAmount = 0;
                $detailsData = [];

                foreach ($data['details'] as $detail) {
                    // 记录每条明细数据
                    file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - 处理明细: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                    // 验证明细数据
                    if ( !isset($detail['actual_quantity'])) {
                        file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - 明细数据验证失败: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                        throw new \Exception('物料ID和数量不能为空');
                    }

                    // 确保数值类型正确
                    $material_id = intval($detail['material_id']) ?? 0;
                    $product_id = intval($detail['product_id']) ?? 0;
                    $quantity = floatval($detail['actual_quantity']);
                    $unit_price = floatval($detail['unit_price'] ?? 0);
                    $amount = $unit_price * $quantity;
                    $totalAmount += $amount;

                    // 查询warehouse_outbound_detail表结构
                    $tableInfo = Db::query("SHOW COLUMNS FROM fy_warehouse_outbound_detail");
                    $fields = array_column($tableInfo, 'Field');
                    file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - 表字段: ' . json_encode($fields, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                    // 准备明细数据
                    $detailData = [
                        'outbound_id' => $outboundId,
                        'product_id' => $product_id,
                        'material_id' => $material_id,
                        'actual_quantity' => $quantity,
                        'unit_price' => $unit_price,
                        'amount' => $amount,
                        'batch_no' => $detail['batch_no'] ?? '',
                        'remark' => $detail['remark'] ?? '',
                        'create_time' => date('Y-m-d H:i:s'),
                        'update_time' => date('Y-m-d H:i:s')
                    ];


                    // 检查是否有shelf_id字段
                    if (in_array('shelf_id', $fields) && !empty($detail['shelf_id'])) {
                        $detailData['shelf_id'] = intval($detail['shelf_id']);
                    }

                    $detailsData[] = $detailData;
                }

                // 记录明细数据
                file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - 明细数据: ' . json_encode($detailsData, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                // 批量插入明细数据
                if (!empty($detailsData)) {
                    Db::name('warehouse_outbound_detail')->insertAll($detailsData);


                    if ($mainData['status'] == 2) {
                        if ($mainData['type'] == 100) {  //物料
                            foreach ($detailsData as $value) {  //更新库存
                                (new MaterialCategoryModel())->stockInOut($value['material_id'], $quantity, '出库单(出库)',
                                    $outboundId, 100);
                            }
                        } else { //产品
                            foreach ($detailsData as $value) {  //更新库存
                                (new MaterialCategoryModel())->stockInOutProduct($value['product_id'], $quantity, '出库单(出库)',
                                    $outboundId, 100);
                            }
                        }

                    }

                } else {
                    throw new \Exception('没有详情数据');
                }

                // 更新主表总金额
                Db::name('warehouse_outbound')->where('id', $outboundId)->update([
                    'total_amount' => $totalAmount,
                    'update_time' => date('Y-m-d H:i:s')
                ]);
            } else {
                file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - 没有明细数据或格式不正确: ' . json_encode($data['details'] ?? null, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
            }

            Db::commit();
            return json(['code' => 200, 'msg' => '添加成功', 'data' => ['id' => $outboundId]]);
        } catch (\Exception $e) {
            Db::rollback();
            file_put_contents(__DIR__ . '/log250825/outbound_add.log', date('Y-m-d H:i:s') . ' - 异常: ' . $e->getMessage() . PHP_EOL . $e->getTraceAsString() . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => '添加失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 更新出库单
     */
    public function updateOutbound()
    {
        $data = Request::post();

        // 记录接收到的数据
        file_put_contents(__DIR__ . '/log250825/outbound_update.log', date('Y-m-d H:i:s') . ' - 接收到的数据: ' . json_encode($data, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

        // 检查数据类型
        if (isset($data['details'])) {
            if (!is_array($data['details'])) {
                file_put_contents(__DIR__ . '/log250825/outbound_update.log', date('Y-m-d H:i:s') . ' - details不是数组: ' . gettype($data['details']) . PHP_EOL, FILE_APPEND);
                // 尝试解码JSON字符串
                if (is_string($data['details'])) {
                    $data['details'] = json_decode($data['details'], true);
                    file_put_contents(__DIR__ . '/log250825/outbound_update.log', date('Y-m-d H:i:s') . ' - 解码后的details: ' . json_encode($data['details'], JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                }
            }
        }

        $validate = Validate::rule([
            'id' => 'require|number',
            'outbound_type' => 'require',
            'operator_id' => 'require|number',
            'warehouse_id' => 'require|number',
            'outbound_date' => 'require|date',
            'status' => 'require|number',
            'type' => 'require|in:100,200',
        ]);

        if (!$validate->check($data)) {
            $errorMsg = $validate->getError();
            file_put_contents(__DIR__ . '/log250825/outbound_update.log', date('Y-m-d H:i:s') . ' - 验证失败: ' . $errorMsg . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => $errorMsg]);
        }

        // 检查出库单是否存在
        $outbound = Db::name('warehouse_outbound')->where('id', $data['id'])->find();
        if (!$outbound) {
            return json(['code' => 404, 'msg' => '出库单不存在']);
        }
        if ($outbound['status'] == 2) {
            return json(['code' => 400, 'msg' => '出库单已审核，请勿修改']);
        }

        if ($data['type'] == 100) {
            foreach ($data['details'] as $item) {
                $material = MaterialCategoryModel::where('id', $item['material_id'])->find();
                if ($material->current_quantity < $item['quantity']) {
                    return json(['code' => 400, 'msg' => $material['material_name'] . '库存不足']);
                }
            }
        } else {
            foreach ($data['details'] as $item) {
                $product = ProductModel::where('id', $item['product_id'])->find();
                if ($product->current_quantity < $item['quantity']) {
                    return json(['code' => 400, 'msg' => $product['product_name'] . '库存不足']);
                }
            }
        }


        // 开启事务
        Db::startTrans();
        try {
            // 处理主表数据
            $mainData = [
                'outbound_type' => $data['outbound_type'],
                'related_order_no' => $data['related_order_no'] ?? '',
                'warehouse_id' => $data['warehouse_id'],
                'outbound_date' => $data['outbound_date'],
                'operator_id' => $data['operator_id'],
                'status' => $data['status'],
                'type' => $data['type'],
                'remark' => $data['remark'] ?? '',
                'update_time' => date('Y-m-d H:i:s')
            ];

            // 只有当customer_id存在且不为undefined时才添加
            if (isset($data['customer_id']) && $data['customer_id'] !== 'undefined' && $data['customer_id'] !== '') {
                $mainData['customer_id'] = intval($data['customer_id']);
            }

            // 如果原状态未审核，新状态为已审核，添加审核信息
            if ($outbound['status'] == 1 && $data['status'] == 2) {
                $mainData['reviewer_id'] = $data['operator_id']; // 默认审核人为操作人
                $mainData['review_time'] = date('Y-m-d H:i:s');
            }


            // 更新主表数据
            Db::name('warehouse_outbound')->where('id', $data['id'])->update($mainData);

            // 处理明细表数据
            if (!empty($data['details']) && is_array($data['details'])) {
                // 删除原有明细
                Db::name('warehouse_outbound_detail')->where('outbound_id', $data['id'])->delete();

                $totalAmount = 0;
                $detailsData = [];

                // 查询warehouse_outbound_detail表结构
                $tableInfo = Db::query("SHOW COLUMNS FROM fy_warehouse_outbound_detail");
                $fields = array_column($tableInfo, 'Field');
                file_put_contents(__DIR__ . '/log250825/outbound_update.log', date('Y-m-d H:i:s') . ' - 表字段: ' . json_encode($fields, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                foreach ($data['details'] as $detail) {
                    // 记录每条明细数据
                    file_put_contents(__DIR__ . '/log250825/outbound_update.log', date('Y-m-d H:i:s') . ' - 处理明细: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                    // 验证明细数据
                    if ( !isset($detail['actual_quantity'])) {
                        file_put_contents(__DIR__ . '/log250825/outbound_update.log', date('Y-m-d H:i:s') . ' - 明细数据验证失败: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                        throw new \Exception('物料ID和数量不能为空');
                    }

                    // 确保数值类型正确
                    $material_id = intval($detail['material_id']);
                    $product_id = intval($detail['product_id']);
                    $quantity = floatval($detail['actual_quantity']);
                    $unit_price = floatval($detail['unit_price'] ?? 0);
                    $amount = $unit_price * $quantity;
                    $totalAmount += $amount;

                    // 准备明细数据
                    $detailData = [
                        'outbound_id' => $data['id'],
                        'material_id' => $material_id,
                        'product_id' => $product_id,
                        'unit_price' => $unit_price,
                        'amount' => $amount,
                        'actual_quantity' => $quantity,
                        'batch_no' => $detail['batch_no'] ?? '',
                        'remark' => $detail['remark'] ?? '',
                        'create_time' => date('Y-m-d H:i:s'),
                        'update_time' => date('Y-m-d H:i:s')
                    ];

                    // 检查表中是否有quantity字段
//                    if (in_array('quantity', $fields)) {
//                        $detailData['quantity'] = $quantity;
//                    } else {
//                        // 如果没有quantity字段，可能有其他名称的字段表示数量
//                        if (in_array('outbound_quantity', $fields)) {
//                            $detailData['outbound_quantity'] = $quantity;
//                        }
//                    }

                    // 检查是否有shelf_id字段
                    if (in_array('shelf_id', $fields) && !empty($detail['shelf_id'])) {
                        $detailData['shelf_id'] = intval($detail['shelf_id']);
                    }

                    $detailsData[] = $detailData;
                }

                // 记录明细数据
                file_put_contents(__DIR__ . '/log250825/outbound_update.log', date('Y-m-d H:i:s') . ' - 明细数据: ' . json_encode($detailsData, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                // 批量插入明细数据
                if (!empty($detailsData)) {
                    Db::name('warehouse_outbound_detail')->insertAll($detailsData);
                    if ($mainData['status'] == 2) {
                        if ($mainData['type'] == 100) { // 物料
                            foreach ($detailsData as $value) {  //更新库存
                                (new MaterialCategoryModel())->stockInOut($value['material_id'], $quantity, '出库单(出库)',
                                    $outbound['id'], 100);
                            }
                        } else {  //产品
                            foreach ($detailsData  as $value) {  //更新库存
                                (new MaterialCategoryModel())->stockInOutProduct($value['product_id'], $quantity, '出库单(出库)',
                                    $outbound['id'], 100);
                            }
                        }


                    }

                }

                // 更新主表总金额
                Db::name('warehouse_outbound')->where('id', $data['id'])->update([
                    'total_amount' => $totalAmount,
                    'update_time' => date('Y-m-d H:i:s')
                ]);
            } else {
                file_put_contents(__DIR__ . '/log250825/outbound_update.log', date('Y-m-d H:i:s') . ' - 没有明细数据或格式不正确: ' . json_encode($data['details'] ?? null, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
            }

            Db::commit();
            return json(['code' => 200, 'msg' => '更新成功']);
        } catch (\Exception $e) {
            Db::rollback();
            file_put_contents(__DIR__ . '/log250825/outbound_update.log', date('Y-m-d H:i:s') . ' - 异常: ' . $e->getMessage() . PHP_EOL . $e->getTraceAsString() . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => '更新失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 删除出库单
     */
    public function deleteOutbound()
    {
        $id = Request::param('id');
        $ids = Request::param('ids');

        if (empty($id) && empty($ids)) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }

        Db::startTrans();
        try {
            if (!empty($ids)) {
                // 批量删除
                $idArray = explode(',', $ids);
                foreach ($idArray as $outboundId) {
                    // 删除出库单明细
                    Db::name('warehouse_outbound_detail')->where('outbound_id', $outboundId)->delete();
                    // 删除出库单
                    Db::name('warehouse_outbound')->delete($outboundId);
                }
            } else {
                // 单个删除
                // 删除出库单明细
                Db::name('warehouse_outbound_detail')->where('outbound_id', $id)->delete();
                // 删除出库单
                Db::name('warehouse_outbound')->delete($id);
            }

            Db::commit();
            return json(['code' => 200, 'msg' => '删除成功']);
        } catch (\Exception $e) {
            Db::rollback();
            return json(['code' => 400, 'msg' => '删除失败：' . $e->getMessage()]);
        }
    }

    /**
     * 获取出库单详情
     */
    public function getOutboundDetail()
    {
        $id = Request::param('id');

        if (empty($id)) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }

        // 获取出库单主表信息
        $outbound = Db::name('warehouse_outbound')
            ->alias('wo')
            ->leftJoin('user u', 'wo.operator_id = u.id')
            ->leftJoin('user ur', 'wo.reviewer_id = ur.id')
            ->leftJoin('customer c', 'wo.customer_id = c.id')
            ->leftJoin('warehouse w', 'wo.warehouse_id = w.id')
            ->field('wo.*, u.realname as operator_name, ur.realname as reviewer_name, c.customer_name, w.warehouse_name')
            ->where('wo.id', $id)
            ->find();

        if (!$outbound) {
            return json(['code' => 404, 'msg' => '出库单不存在']);
        }
        if($outbound['type'] == 100){
            // 获取出库单明细
            $details = Db::name('warehouse_outbound_detail')
                ->alias('wod')
                ->leftJoin('material_category mc', 'wod.material_id = mc.id')
                ->leftJoin('shelf s', 'wod.shelf_id = s.id')
                ->field('wod.*, mc.material_name, mc.material_code, s.shelf_code')
                ->where('wod.outbound_id', $id)
                ->select()
                ->toArray();
        }else{
            // 获取出库单明细
            $details = Db::name('warehouse_outbound_detail')
                ->alias('wod')
                ->leftJoin('product p', 'wod.product_id = p.id')
                ->leftJoin('shelf s', 'wod.shelf_id = s.id')
                ->field('wod.*,  p.product_name, p.product_code, s.shelf_code')
                ->where('wod.outbound_id', $id)
                ->select()
                ->toArray();
        }



        $outbound['details'] = $details;

        return json(['code' => 200, 'msg' => '获取成功', 'data' => $outbound]);
    }

    /**
     * 获取领料单列表
     */
    public function getRequisitionList()
    {
        $page = (int)Request::param('page', 1);
        $limit = (int)Request::param('limit', 10);
        $search = Request::param('search', '');
        $status = Request::param('status', '');

        $where = [];
        if (!empty($search)) {
            $where[] = ['requisition_no', 'like', "%{$search}%"];
        }

        if ($status !== '') {
            $where[] = ['status', '=', (int)$status];
        }

        // 获取领料单列表
        $list = Db::name('warehouse_requisition')
            ->alias('wr')
            ->leftJoin('user u', 'wr.applicant_id = u.id')
            ->leftJoin('user_department ud', 'wr.department_id = ud.id')
            ->field('wr.*, u.realname as applicant_name, ud.name as department_name')
            ->where($where)
            ->page($page, $limit)
            ->order('wr.id', 'desc')
            ->select()
            ->toArray();

        $count = Db::name('warehouse_requisition')->where($where)->count();

        // 修改返回格式，将list和total包装在data对象中
        return json(['code' => 200, 'msg' => '获取成功', 'data' => ['list' => $list, 'total' => $count]]);
    }

    /**
     * 添加领料单
     */
    public function addRequisition()
    {
        $data = Request::post();

        // 记录接收到的数据
        file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - 接收到的数据: ' . json_encode($data, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

        // 检查数据类型
        if (isset($data['details'])) {
            if (!is_array($data['details'])) {
                file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - details不是数组: ' . gettype($data['details']) . PHP_EOL, FILE_APPEND);
                // 尝试解码JSON字符串
                if (is_string($data['details'])) {
                    $data['details'] = json_decode($data['details'], true);
                    file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - 解码后的details: ' . json_encode($data['details'], JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                }
            }
        }

        $validate = Validate::rule([
            'applicant_id' => 'require|number',
            'department_id' => 'require|number',
            'purpose' => 'require',
            'status' => 'require|number',
        ]);

        if (!$validate->check($data)) {
            $errorMsg = $validate->getError();
            file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - 验证失败: ' . $errorMsg . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => $errorMsg]);
        }

        // 开启事务
        Db::startTrans();
        try {
            // 生成领料单号 (更短的格式)
            $data['requisition_no'] = 'LL' . date('ymdHis') . rand(10, 99);

            // 处理主表数据
            $mainData = [
                'requisition_no' => $data['requisition_no'],
                'applicant_id' => $data['applicant_id'],
                'department_id' => $data['department_id'],
                'purpose' => $data['purpose'],
                'status' => $data['status'],
                'remark' => $data['remark'] ?? '',
                'create_time' => date('Y-m-d H:i:s'),
                'update_time' => date('Y-m-d H:i:s')
            ];

            // 记录主表数据
            file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - 主表数据: ' . json_encode($mainData, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

            // 插入主表数据
            $requisitionId = Db::name('warehouse_requisition')->insertGetId($mainData);

            // 处理明细表数据
            if (!empty($data['details']) && is_array($data['details'])) {
                $detailsData = [];

                // 查询warehouse_requisition_detail表结构
                $tableInfo = Db::query("SHOW COLUMNS FROM fy_warehouse_requisition_detail");
                $fields = array_column($tableInfo, 'Field');
                file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - 表字段: ' . json_encode($fields, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                foreach ($data['details'] as $detail) {
                    // 记录每条明细数据
                    file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - 处理明细: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                    // 验证明细数据
                    if (empty($detail['material_id']) || !isset($detail['quantity'])) {
                        file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - 明细数据验证失败: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                        throw new \Exception('物料ID和数量不能为空');
                    }

                    // 确保数值类型正确
                    $material_id = intval($detail['material_id']);
                    $quantity = floatval($detail['quantity']);

                    // 准备明细数据
                    $detailData = [
                        'requisition_id' => $requisitionId,
                        'material_id' => $material_id,
                        'remark' => $detail['remark'] ?? '',
                        'create_time' => date('Y-m-d H:i:s'),
                        'update_time' => date('Y-m-d H:i:s')
                    ];

                    // 检查表中是否有quantity字段
                    if (in_array('quantity', $fields)) {
                        $detailData['quantity'] = $quantity;
                    } else {
                        // 如果没有quantity字段，可能有其他名称的字段表示数量
                        if (in_array('requisition_quantity', $fields)) {
                            $detailData['requisition_quantity'] = $quantity;
                        }
                    }

                    $detailsData[] = $detailData;
                }

                // 记录明细数据
                file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - 明细数据: ' . json_encode($detailsData, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                // 批量插入明细数据
                if (!empty($detailsData)) {
                    Db::name('warehouse_requisition_detail')->insertAll($detailsData);
                }
            } else {
                file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - 没有明细数据或格式不正确: ' . json_encode($data['details'] ?? null, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
            }

            Db::commit();
            return json(['code' => 200, 'msg' => '添加成功', 'data' => ['id' => $requisitionId]]);
        } catch (\Exception $e) {
            Db::rollback();
            file_put_contents(__DIR__ . '/log250825/requisition_add.log', date('Y-m-d H:i:s') . ' - 异常: ' . $e->getMessage() . PHP_EOL . $e->getTraceAsString() . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => '添加失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 更新领料单
     */
    public function updateRequisition()
    {
        $data = Request::post();

        // 记录接收到的数据
        file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - 接收到的数据: ' . json_encode($data, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

        // 检查数据类型
        if (isset($data['details'])) {
            if (!is_array($data['details'])) {
                file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - details不是数组: ' . gettype($data['details']) . PHP_EOL, FILE_APPEND);
                // 尝试解码JSON字符串
                if (is_string($data['details'])) {
                    $data['details'] = json_decode($data['details'], true);
                    file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - 解码后的details: ' . json_encode($data['details'], JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                }
            }
        }

        $validate = Validate::rule([
            'id' => 'require|number',
            'department_id' => 'require|number',
            'applicant_id' => 'require|number',
            'purpose' => 'require',
            'status' => 'require|number',
        ]);

        if (!$validate->check($data)) {
            $errorMsg = $validate->getError();
            file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - 验证失败: ' . $errorMsg . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => $errorMsg]);
        }

        // 检查领料单是否存在
        $requisition = Db::name('warehouse_requisition')->where('id', $data['id'])->find();
        if (!$requisition) {
            return json(['code' => 404, 'msg' => '领料单不存在']);
        }

        // 开启事务
        Db::startTrans();
        try {
            // 处理主表数据
            $mainData = [
                'applicant_id' => $data['applicant_id'],
                'department_id' => $data['department_id'],
                'purpose' => $data['purpose'],
                'status' => $data['status'],
                'remark' => $data['remark'] ?? '',
                'update_time' => date('Y-m-d H:i:s')
            ];

            // 记录主表数据
            file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - 主表数据: ' . json_encode($mainData, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

            // 更新主表数据
            Db::name('warehouse_requisition')->where('id', $data['id'])->update($mainData);

            // 处理明细表数据
            if (!empty($data['details']) && is_array($data['details'])) {
                // 删除原有明细
                Db::name('warehouse_requisition_detail')->where('requisition_id', $data['id'])->delete();

                $detailsData = [];

                // 查询warehouse_requisition_detail表结构
                $tableInfo = Db::query("SHOW COLUMNS FROM fy_warehouse_requisition_detail");
                $fields = array_column($tableInfo, 'Field');
                file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - 表字段: ' . json_encode($fields, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                foreach ($data['details'] as $detail) {
                    // 记录每条明细数据
                    file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - 处理明细: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                    // 验证明细数据
                    if (empty($detail['material_id']) || !isset($detail['quantity'])) {
                        file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - 明细数据验证失败: ' . json_encode($detail, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
                        throw new \Exception('物料ID和数量不能为空');
                    }

                    // 确保数值类型正确
                    $material_id = intval($detail['material_id']);
                    $quantity = floatval($detail['quantity']);

                    // 准备明细数据
                    $detailData = [
                        'requisition_id' => $data['id'],
                        'material_id' => $material_id,
                        'remark' => $detail['remark'] ?? '',
                        'create_time' => date('Y-m-d H:i:s'),
                        'update_time' => date('Y-m-d H:i:s')
                    ];

                    // 检查表中是否有quantity字段
                    if (in_array('quantity', $fields)) {
                        $detailData['quantity'] = $quantity;
                    } else {
                        // 如果没有quantity字段，可能有其他名称的字段表示数量
                        if (in_array('requisition_quantity', $fields)) {
                            $detailData['requisition_quantity'] = $quantity;
                        }
                    }

                    $detailsData[] = $detailData;
                }

                // 记录明细数据
                file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - 明细数据: ' . json_encode($detailsData, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);

                // 批量插入明细数据
                if (!empty($detailsData)) {
                    Db::name('warehouse_requisition_detail')->insertAll($detailsData);
                }
            } else {
                file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - 没有明细数据或格式不正确: ' . json_encode($data['details'] ?? null, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
            }

            Db::commit();
            return json(['code' => 200, 'msg' => '更新成功']);
        } catch (\Exception $e) {
            Db::rollback();
            file_put_contents(__DIR__ . '/log250825/requisition_update.log', date('Y-m-d H:i:s') . ' - 异常: ' . $e->getMessage() . PHP_EOL . $e->getTraceAsString() . PHP_EOL, FILE_APPEND);
            return json(['code' => 400, 'msg' => '更新失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 删除领料单
     */
    public function deleteRequisition()
    {
        $id = Request::param('id');
        $ids = Request::param('ids');

        if (empty($id) && empty($ids)) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }

        Db::startTrans();
        try {
            if (!empty($ids)) {
                // 批量删除
                $idArray = explode(',', $ids);
                foreach ($idArray as $requisitionId) {
                    // 删除领料单明细
                    Db::name('warehouse_requisition_detail')->where('requisition_id', $requisitionId)->delete();
                    // 删除领料单
                    Db::name('warehouse_requisition')->delete($requisitionId);
                }
            } else {
                // 单个删除
                // 删除领料单明细
                Db::name('warehouse_requisition_detail')->where('requisition_id', $id)->delete();
                // 删除领料单
                Db::name('warehouse_requisition')->delete($id);
            }

            Db::commit();
            return json(['code' => 200, 'msg' => '删除成功']);
        } catch (\Exception $e) {
            Db::rollback();
            return json(['code' => 400, 'msg' => '删除失败：' . $e->getMessage()]);
        }
    }

    /**
     * 获取领料单详情
     */
    public function getRequisitionDetail()
    {
        $id = Request::param('id');

        if (empty($id)) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }

        // 获取领料单主表信息
        $requisition = Db::name('warehouse_requisition')
            ->alias('wr')
            ->leftJoin('user u', 'wr.applicant_id = u.id')
            ->leftJoin('user_department ud', 'wr.department_id = ud.id')
            ->field('wr.*, u.realname as applicant_name, ud.name as department_name')
            ->where('wr.id', $id)
            ->find();

        if (!$requisition) {
            return json(['code' => 404, 'msg' => '领料单不存在']);
        }

        // 获取领料单明细
        $details = Db::name('warehouse_requisition_detail')
            ->alias('wrd')
            ->leftJoin('material_category mc', 'wrd.material_id = mc.id')
            ->field('wrd.*, mc.material_name, mc.material_code')
            ->where('wrd.requisition_id', $id)
            ->select()
            ->toArray();

        $requisition['details'] = $details;

        return json(['code' => 200, 'msg' => '获取成功', 'data' => $requisition]);
    }

    /**
     * 获取库存盘点列表
     */
    public function getInventoryCheckList()
    {
        $page = (int)Request::param('page', 1);
        $limit = (int)Request::param('limit', 10);
        $search = Request::param('search', '');
        $status = Request::param('status', '');

        $where = [];
        if (!empty($search)) {
            $where[] = ['check_no', 'like', "%{$search}%"];
        }

        if ($status !== '') {
            $where[] = ['status', '=', (int)$status];
        }

        // 获取库存盘点列表
        $list = Db::name('warehouse_inventory_check')
            ->alias('wic')
            ->leftJoin('user u', 'wic.operator_id = u.id')
            ->leftJoin('warehouse w', 'wic.warehouse_id = w.id')
            ->field('wic.*, u.realname as operator_name, w.warehouse_name')
            ->where($where)
            ->page($page, $limit)
            ->order('wic.id', 'desc')
            ->select()
            ->toArray();

        $count = Db::name('warehouse_inventory_check')->where($where)->count();

        // 修改返回格式，将list和total包装在data对象中
        return json(['code' => 200, 'msg' => '获取成功', 'data' => ['list' => $list, 'total' => $count]]);
    }

    /**
     * 添加库存盘点
     */
    public function addInventoryCheck()
    {
        $data = Request::post();

        $validate = Validate::rule([
            'operator_id' => 'require|number',
            'warehouse_id' => 'require|number',
            'check_type' => 'require',
            'status' => 'require|number',
        ]);

        if (!$validate->check($data)) {
            return json(['code' => 400, 'msg' => $validate->getError()]);
        }

        // 生成盘点单号 (更短的格式)
        $data['check_no'] = 'PD' . date('ymdHis') . rand(10, 99);
        $data['create_time'] = date('Y-m-d H:i:s');

        $result = Db::name('warehouse_inventory_check')->insert($data);

        if ($result) {
            return json(['code' => 200, 'msg' => '添加成功']);
        } else {
            return json(['code' => 400, 'msg' => '添加失败']);
        }
    }

    /**
     * 更新库存盘点
     */
    public function updateInventoryCheck()
    {
        $data = Request::post();

        $validate = Validate::rule([
            'id' => 'require|number',
            'check_date' => 'require|date',
            'operator_id' => 'require|number',
            'status' => 'require|number',
        ]);

        if (!$validate->check($data)) {
            return json(['code' => 400, 'msg' => $validate->getError()]);
        }

        $data['update_time'] = date('Y-m-d H:i:s');
        $result = Db::name('warehouse_inventory_check')->update($data);

        if ($result) {
            return json(['code' => 200, 'msg' => '更新成功']);
        } else {
            return json(['code' => 400, 'msg' => '更新失败']);
        }
    }

    /**
     * 删除库存盘点
     */
    public function deleteInventoryCheck()
    {
        $id = Request::param('id');

        if (empty($id)) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }

        $result = Db::name('warehouse_inventory_check')->delete($id);

        if ($result) {
            return json(['code' => 200, 'msg' => '删除成功']);
        } else {
            return json(['code' => 400, 'msg' => '删除失败']);
        }
    }

    /**
     * 库存查询
     */
    public function getInventoryList()
    {
        $page = Request::param('page', 1);
        $limit = Request::param('limit', 10);
        $search = Request::param('search', '');
        $shelf_id = Request::param('shelf_id', '');

        $where = [];
        if (!empty($search)) {
            $materialIds = Db::name('material_category')
                ->where('material_name', 'like', "%{$search}%")
                ->whereOr('material_code', 'like', "%{$search}%")
                ->column('id');
            if (!empty($materialIds)) {
                $where[] = ['id', 'in', $materialIds];
            }
        }

        if ($shelf_id !== '') {
            $where[] = ['shelf_id', '=', $shelf_id];
        }

        $count = Db::name('material_category')->where($where)->count();
        $list = Db::name('material_category')
            ->where($where)
            ->page($page, $limit)
            ->order('id', 'desc')
            ->select()
            ->toArray();

        // 关联货架信息
        foreach ($list as &$item) {
            $shelf = Db::name('shelf')->where('id', $item['shelf_id'])->find();
            $item['shelf_code'] = $shelf ? $shelf['shelf_code'] : '';
        }

        return json(['code' => 200, 'msg' => '获取成功', 'data' => $list, 'count' => $count]);
    }

    /**
     * 获取库存预警列表
     */
    public function getInventoryWarningList()
    {
        $page = (int)Request::param('page', 1);
        $limit = (int)Request::param('limit', 10);

        // 获取所有物料的当前库存和预警设置
        $inventoryQuery = Db::name('warehouse_inventory')
            ->alias('wi')
            ->leftJoin('material_category mc', 'wi.material_id = mc.id')
            ->leftJoin('shelf s', 'wi.shelf_id = s.id')
            ->leftJoin('warehouse w', 'wi.warehouse_id = w.id')
            ->leftJoin('material_warning mw', 'wi.material_id = mw.material_id AND (wi.warehouse_id = mw.warehouse_id OR mw.warehouse_id IS NULL)')
            ->field('wi.id, wi.material_id, mc.material_code, mc.material_name, 
                    wi.quantity as current_quantity, 
                    mw.min_quantity as warning_quantity, 
                    wi.shelf_id, s.shelf_code, 
                    wi.warehouse_id, w.warehouse_name, 
                    wi.update_time as last_update_time')
            ->where('mw.min_quantity > 0') // 只查询设置了最小库存的物料
            ->where(function ($query) {
                $query->whereRaw('wi.quantity <= mw.min_quantity') // 库存低于或等于最小库存
                ->whereOr('wi.quantity >= mw.max_quantity'); // 或库存高于或等于最大库存
            });

        $count = $inventoryQuery->count();
        $list = $inventoryQuery->page($page, $limit)->select()->toArray();

        // 修改返回格式，将list和total包装在data对象中
        return json(['code' => 200, 'msg' => '获取成功', 'data' => ['list' => $list, 'total' => $count]]);
    }

    /**
     * 更新库存
     * @param int $materialId 物料ID
     * @param float $quantity 数量
     * @param string $type 类型：in-入库，out-出库
     * @param int $warehouseId 仓库ID
     * @param int|null $shelfId 货架ID
     * @param string $batchNo 批次号
     * @param string|null $productionDate 生产日期
     * @param float $unitPrice 单价
     * @return bool
     */
    private function updateInventory($materialId, $quantity, $type, $warehouseId, $shelfId = null, $batchNo = '', $productionDate = null, $unitPrice = 0)
    {
        if (empty($materialId) || empty($quantity) || empty($warehouseId)) {
            return false;
        }

        // 记录库存事务
        $transactionData = [
            'material_id' => $materialId,
            'warehouse_id' => $warehouseId,
            'shelf_id' => $shelfId,
            'batch_no' => $batchNo,
            'quantity' => $type == 'in' ? $quantity : -$quantity,
            'unit_price' => $unitPrice,
            'transaction_type' => $type == 'in' ? 1 : 2, // 1-入库，2-出库
            'transaction_time' => date('Y-m-d H:i:s'),
            'create_time' => date('Y-m-d H:i:s'),
            'update_time' => date('Y-m-d H:i:s')
        ];

        Db::name('inventory_transaction')->insert($transactionData);

        // 检查是否存在相同批次的库存记录
        $inventory = Db::name('warehouse_inventory')
            ->where([
                ['material_id', '=', $materialId],
                ['warehouse_id', '=', $warehouseId],
                ['shelf_id', '=', $shelfId],
                ['batch_no', '=', $batchNo]
            ])
            ->find();

        if ($inventory) {
            // 更新现有库存
            $newQuantity = $type == 'in' ?
                $inventory['quantity'] + $quantity :
                $inventory['quantity'] - $quantity;

            // 计算新的可用数量
            $availableQuantity = $newQuantity - $inventory['reserved_quantity'];

            // 如果是出库，需要检查库存是否足够
            if ($type == 'out' && $newQuantity < 0) {
                throw new \Exception('库存不足');
            }

            // 更新库存记录
            Db::name('warehouse_inventory')->where('id', $inventory['id'])->update([
                'quantity' => $newQuantity,
                'available_quantity' => $availableQuantity,
                'update_time' => date('Y-m-d H:i:s')
            ]);
        } else {
            // 创建新的库存记录
            if ($type == 'out') {
                throw new \Exception('库存不足');
            }

            Db::name('warehouse_inventory')->insert([
                'material_id' => $materialId,
                'warehouse_id' => $warehouseId,
                'shelf_id' => $shelfId,
                'batch_no' => $batchNo,
                'quantity' => $quantity,
                'reserved_quantity' => 0,
                'available_quantity' => $quantity,
                'unit_price' => $unitPrice,
                'production_date' => $productionDate,
                'expiry_date' => null, // 移除对expiry_date的使用
                'status' => 1,
                'create_time' => date('Y-m-d H:i:s'),
                'update_time' => date('Y-m-d H:i:s')
            ]);
        }

        // 更新物料分类表中的当前数量
        $this->updateMaterialCurrentQuantity($materialId, $type, $quantity);

        // 检查是否需要触发库存预警
        $this->checkInventoryWarning($materialId, $warehouseId);

        return true;
    }

    /**
     * 更新物料分类表中的当前数量
     * @param int $materialId 物料ID
     * @param string $type 类型：in-入库，out-出库
     * @param float $quantity 数量
     */
    private function updateMaterialCurrentQuantity($materialId, $type, $quantity)
    {
        // 获取物料当前库存
        $material = Db::name('material_category')->where('id', $materialId)->find();
        if (!$material) {
            return;
        }

        // 计算新的库存数量
        $currentQuantity = $material['current_quantity'] ?? 0;
        $newQuantity = $type == 'in' ? $currentQuantity + $quantity : $currentQuantity - $quantity;

        // 如果是出库，确保库存不会小于0
        if ($type == 'out' && $newQuantity < 0) {
            $newQuantity = 0;
        }

        // 更新物料分类表中的当前数量
        Db::name('material_category')->where('id', $materialId)->update([
            'current_quantity' => $newQuantity,
            'update_time' => date('Y-m-d H:i:s')
        ]);

        // 记录日志
        file_put_contents(__DIR__ . '/log250825/material_update.log', date('Y-m-d H:i:s') . ' - 更新物料库存: ' . json_encode([
                'material_id' => $materialId,
                'type' => $type,
                'quantity' => $quantity,
                'old_quantity' => $currentQuantity,
                'new_quantity' => $newQuantity
            ], JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
    }

    /**
     * 检查库存预警
     * @param int $materialId 物料ID
     * @param int $warehouseId 仓库ID
     */
    private function checkInventoryWarning($materialId, $warehouseId)
    {
        // 获取物料当前库存
        $inventory = Db::name('warehouse_inventory')
            ->where([
                ['material_id', '=', $materialId],
                ['warehouse_id', '=', $warehouseId]
            ])
            ->sum('quantity');

        // 获取物料预警设置
        $warning = Db::name('material_warning')
            ->where([
                ['material_id', '=', $materialId],
                ['warehouse_id', '=', $warehouseId]
            ])
            ->find();

        if (!$warning) {
            // 获取物料全局预警设置
            $warning = Db::name('material_warning')
                ->where([
                    ['material_id', '=', $materialId],
                    ['warehouse_id', 'is', null]
                ])
                ->find();
        }

        if ($warning) {
            // 检查是否低于最小库存
            if ($inventory <= $warning['min_quantity']) {
                // 触发库存不足预警
                // 这里可以添加发送通知的代码
            }

            // 检查是否超过最大库存
            if ($inventory >= $warning['max_quantity']) {
                // 触发库存过剩预警
                // 这里可以添加发送通知的代码
            }
        }
    }

    /**
     * 获取货架列表
     */
    public function getShelfList()
    {
        $list = Db::name('shelf')
            ->order('shelf_code', 'asc')
            ->select()
            ->toArray();

        return json(['code' => 200, 'msg' => '获取成功', 'data' => ['list' => $list, 'total' => count($list)]]);
    }

    /**
     * 获取物料列表
     */
    public function getMaterialList()
    {
        $list = Db::name('material_category')
            ->order('material_name', 'asc')
            ->select()
            ->toArray();

        return json(['code' => 200, 'msg' => '获取成功', 'data' => ['list' => $list, 'total' => count($list)]]);
    }

    /**
     * 获取仓库列表
     */
    public function getWarehouseList()
    {
        $list = Db::name('warehouse')
            ->where('status', 1)
            ->order('warehouse_code', 'asc')
            ->select()
            ->toArray();

        return json(['code' => 200, 'msg' => '获取成功', 'data' => ['list' => $list, 'total' => count($list)]]);
    }
}